import { h } from '@knno/dom/jsx';
import { Group, UIGroup } from '../group';
import { Cell, CellProps, Option } from './cell';
import { checkboxStyle } from './cell.css';
import { Radio } from '../radio';
import IconUnchecked from '@mdi/svg/svg/checkbox-blank-outline.svg';
import IconChecked from '@mdi/svg/svg/checkbox-outline.svg';
import { Checkbox } from '../checkbox';

type CheckType = 'boolean' | 'single' | 'multiple';
type CheckCellValueType<T extends CheckType> = T extends 'boolean'
	? boolean
	: T extends 'single'
	? string
	: T extends 'multiple'
	? string[]
	: never;

type RequireOptions<T extends CheckType> = T extends 'boolean'
	? CheckCellProps<T> & { options?: never }
	: T extends 'single' | 'multiple'
	? CheckCellProps<T> & { options: (Option | string)[] }
	: never;

interface CheckCellProps<T extends CheckType>
	extends CellProps<CheckCell<T>, RequireOptions<T>, CheckCellValueType<T>> {
	type: T;
	value?: CheckCellValueType<T>;
	options?: T extends 'boolean' ? never : (Option | string)[];
}

const GROUP = Symbol('group');

export class CheckCell<T extends CheckType> extends Cell<CheckCell<T>, RequireOptions<T>, CheckCellValueType<T>> {
	private [GROUP]?: UIGroup;

	init() {
		const options: (Option | string)[] = [];
		let multiple = false;
		this.attr('tabindex', '');
		if (this.attrs.type === 'boolean') {
			options.push({ code: 'true', name: '是' });
			options.push({ code: 'false', name: '否' });
		} else {
			options.push(...(this.attrs.options ?? []));
			multiple = this.attrs.type === 'multiple';
		}
		this.addClass('checkbox').append(
			<Group
				ref={(g) => {
					this[GROUP] = g;
					g.on('change', (evt) => {
						evt.stopPropagation();
						if (g.value().length === 0) {
							this.setValue(null);
						} else if (this.attrs.type === 'boolean') {
							this.setValue((g.value()[0] === 'true') as CheckCellValueType<T>);
						} else if (this.attrs.type === 'single') {
							this.setValue(g.value()[0] as CheckCellValueType<T>);
						} else if (this.attrs.type === 'multiple') {
							this.setValue([...g.value()] as CheckCellValueType<T>);
						}
					});
				}}
			>
				{...options.map((o) => {
					if (typeof o === 'string') {
						o = { code: o, name: o };
					}
					if (multiple) {
						return (
							<Checkbox
								disabled={this.attrs.readonly}
								class={checkboxStyle}
								value={o.code + ''}
								facadeIcons={{ checked: IconChecked, unchecked: IconUnchecked }}
							>
								{o.name}
							</Checkbox>
						);
					} else {
						return (
							<Radio
								disabled={this.attrs.readonly}
								class={checkboxStyle}
								value={o.code + ''}
								uncheckable={this.attrs.optional ?? false}
								facadeIcons={{ checked: IconChecked, unchecked: IconUnchecked }}
							>
								{o.name}
							</Radio>
						);
					}
				})}
			</Group>
		);
		this.update();
	}

	protected update(): void {
		const g = this[GROUP];
		if (!g) {
			return;
		}
		if (this.getValue() === null) {
			g.value([]);
		} else if (this.attrs.type === 'boolean') {
			g.value([this.getValue() ? 'true' : 'false']);
		} else if (this.attrs.type === 'single') {
			g.value([this.getValue() as string]);
		} else if (this.attrs.type === 'multiple') {
			g.value(this.getValue() as string[]);
		}
	}
}
